#pragma once
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include "bg_gamestructs.h"

typedef struct gentity_s gentity_t;

/*==============================================*/
/** 
 *  @brief stdcall function pointer declaration.
 *
 *  Declares the type for a STDCALL function pointer
 *  called N with arguments list A adn returning R.
 *
 */
/*==============================================*/

#define STDCALL_FUNCTION( R, N, A )  typedef R (__stdcall *N) A

/*==============================================*/
/**
 *  @brief fastcall function pointer declaration.
 *
 *  Declares the type for a FASTCALL function pointer
 *  called N with arguments list A adn returning R.
 *
 */
/*==============================================*/

#define FASTCALL_FUNCTION( R, N, A ) typedef R (__fastcall *N) A

/*==============================================*/
/**
 *  @brief cdecl function pointer declaration.
 *
 *  Declares the type for a CDECL function pointer
 *  called N with arguments list A adn returning R.
 *
 */
/*==============================================*/

#define CDECL_FUNCTION( R, N, A ) typedef R (__cdecl *N) A

/*==============================================*/
/**
 *  @brief thiscall function pointer declaration.
 *
 *  Declares the type for a THISCALL function pointer
 *  called N with arguments list A adn returning R.
 *
 */
/*==============================================*/

#define THISCALL_FUNCTION( R, N, A ) typedef R (__thiscall *N) A

/*==============================================*/
/*
 * blank function type
 */
/*==============================================*/

#define BLANK_FUNCTION( R, N, A ) typedef R (*N) A

CDECL_FUNCTION(int, vmMainCGAME, ( int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7 ));
CDECL_FUNCTION(void, dllEntryCGAME, (int (__cdecl  *syscallPtr)( int arg,... )));
CDECL_FUNCTION(game_export_t *, GetGameAPIGAME, (game_import_t *import));

//game_import_t
//gi calls are serverside calls that allow you to do various things. They are the equivalent of trap calls in SP.

//syscalls
typedef enum {
	SYSCALL_PRINT,
	SYSCALL_ERROR,
	SYSCALL_STARTSOUND=30,
	SYSCALL_REGISTERSOUND=37,
	SYSCALL_STOP_ALL_FF=41,
	SYSCALL_REGISTERSHADER=48,
	SYSCALL_REGISTERSHADERNOMIP=49,
	SYSCALL_GETGAMESTATE=76,
} syscalls_t;

#ifndef __JAMOD
__declspec(dllexport) void trap_Error(char *error);
__declspec(dllexport) void trap_Printf(char *fmt, ...);
__declspec(dllexport) qhandle_t __fastcall trap_R_RegisterShader(char *path);
__declspec(dllexport) qhandle_t __fastcall trap_R_RegisterShaderNoMip(char *path);
__declspec(dllexport) const char *trap_Argv(int n);
__declspec(dllexport) void trap_Argv2(int n, char *buffer);
__declspec(dllexport) void trap_S_StartSound( vec3_t origin, int entityNum, int channel, sfxHandle_t handle );
__declspec(dllexport) sfxHandle_t __fastcall trap_S_RegisterSound( char *soundName );
__declspec(dllexport) void __cdecl trapped_Cvar_VariableBuffer( const char *var_name, char *buffer, int bufsize );
__declspec(dllexport) int __cdecl trapped_FS_FOpenFile( char *fileName, fileHandle_t *f, fsMode_t mode );
__declspec(dllexport) int __cdecl trapped_FS_Read( void *buffer, int len, fileHandle_t f );
__declspec(dllexport) void __cdecl trapped_FS_FCloseFile( fileHandle_t f );

CDECL_FUNCTION(void, onCGInitX, (void));
CDECL_FUNCTION(void, onCGShutdownX, (void));
CDECL_FUNCTION(void, onCGDrawActiveFrameX, (int serverTime, DWORD *stereoView));
CDECL_FUNCTION(qboolean, onCGConsoleCommandX, (void));
CDECL_FUNCTION(void, OnGamesideInitX, (void));

static onCGInitX onCGInit;
static onCGShutdownX onCGShutdown;
static onCGDrawActiveFrameX onCGDrawActiveFrame;
static onCGConsoleCommandX onCGConsoleCommand;
static OnGamesideInitX OnGamesideInit;

void (*trap_ArgvX)(int n, char *buffer, int bufferLen);
#endif

#define MAX_FAILED_NODES 8
#define MAX_INHAND_WEAPONS	2

#define	MAX_PARMS	16
#define	MAX_PARM_STRING_LENGTH	MAX_QPATH//was 16, had to lengthen it so they could take a valid file path
typedef struct
{	
	char	parm[MAX_PARMS][MAX_PARM_STRING_LENGTH];
} parms_t;

#define thinkFunc_t int
#define clThinkFunc_t int
#define reachedFunc_t int
#define blockedFunc_t int
#define touchFunc_t int
#define useFunc_t int
#define painFunc_t int
#define dieFunc_t int

typedef struct gitem_s {
	char		*classname;	// spawning name
	char		*pickup_sound;
	char		*world_model;

	char		*icon;

	int			quantity;		// for ammo how much, or duration of powerup
	itemType_t  giType;			// IT_* flags

	int			giTag;

	char		*precaches;		// string of all models and images this item will use
	char		*sounds;		// string of all sounds this item will use
	vec3_t		mins;			// Bbox
	vec3_t		maxs;			// Bbox
	char		*pickup_force;
	char		*forces;
} gitem_t;

struct gentity_s {
	//Found the loc of eFlags. It's +8.
	int number;																												//+0
	int eType;																												//+4
	int eFlags;																												//+8
	int eFlags2;																											//+12
	BYTE s2[76];																											//+16
	vec3_t origin;																											//+92
	BYTE s3[12];																											//+104
	vec3_t angles;																											//+116
	BYTE s4[32];																											//+128
	int modelIndex;																											//+160
	BYTE s[108];				// communicated by server to clients
	struct gclient_s	*client;	// NULL if not a player (unless it's NPC ( if (this->NPC != NULL)  )  <sigh>... -slc)	//+272
	qboolean	inuse;																										//+276
	qboolean	linked;				// qfalse if not in any good cluster													//+280

	int			svFlags;			// SVF_NOCLIENT, SVF_BROADCAST, etc														//+284

	qboolean	bmodel;				// if false, assume an explicit mins / maxs bounding box								//+288
									// only set by gi.SetBrushModel
	vec3_t		mins, maxs;																							//+292	//+304
	int			contents;			// CONTENTS_TRIGGER, CONTENTS_SOLID, CONTENTS_BODY, etc									//+316
									// a non-solid entity should set to 0

	vec3_t		absmin, absmax;		// derived from mins/maxs and origin + rotation									//+320	//+332

	// currentOrigin will be used for all collision detection and world linking.
	// it will not necessarily be the same as the trajectory evaluation for the current
	// time, because each entity must be moved one at a time after time is advanced
	// to avoid simultanious collision issues
	vec3_t		currentOrigin;																								//+344
	vec3_t		currentAngles;																								//+356

	gentity_t	*owner;				// objects never interact with their owners, to											//+368
									// prevent player missiles from immediately
									// colliding with their owner
/*
Ghoul2 Insert Start
*/
	// this marker thing of Jake's is used for memcpy() length calcs, so don't put any ordinary fields (like above)
	//	below this point or they won't work, and will mess up all sorts of stuff. 
	//
	void	*ghoul2;			//wow Raven...way to typedef a void * ~eezstreet											//+372

	vec3_t			modelScale; //needed for g2 collision																	//+376
/*
Ghoul2 Insert End
*/

	// DO NOT MODIFY ANYTHING ABOVE THIS, THE SERVER
	// EXPECTS THE FIELDS IN THAT ORDER!

//==========================================================================================

//Essential entity fields
	// note: all the char* fields from here on should be left as ptrs, not declared, because of the way that ent-parsing
	//	works by forcing field offset ptrs as char* and using G_NewString()!! (see G_ParseField() in gmae/g_spawn.cpp -slc
	//
	char		*classname;			// set in QuakeEd																		//+388
	int			spawnflags;			// set in QuakeEd																		//+392

	int			flags;				// FL_* variables																		//+396

	char		*model;				// Normal model, or legs model on tri-models											//+400
	char		*model2;			// Torso model																			//+404

	int			freetime;			// sv.time when the object was freed													//+408
	
	int			eventTime;			// events will be cleared EVENT_VALID_MSEC after set									//+412
	qboolean	freeAfterEvent;																								//+416
//	qboolean	unlinkAfterEvent;

//Physics and movement fields
	float		physicsBounce;		// 1.0 = continuous bounce, 0.0 = no bounce												//+420
	int			clipmask;			// brushes with this content value will be collided against								//+424
									// when moving.  items and corpses do not collide against
									// players, for instance
//	moveInfo_t	moveInfo;		//FIXME: use this more?
	float		speed;																										//+428
	float		resultspeed;																								//+432
	int			lastMoveTime;																								//+436
	vec3_t		movedir;																									//+440
	vec3_t		lastOrigin;			//Where you were last frame																//+452
	vec3_t		lastAngles;			//Where you were looking last frame														//+464
	float		mass;				//How heavy you are																		//+476
	int			lastImpact;			//Last time you impacted something														//+480

//Variables reflecting environment
	int			watertype;																									//+484
	int			waterlevel;																									//+488
	short		wupdate;																									//+492
	short		prev_waterlevel;																							//+494

//Targeting/linking fields
	float		angle;			// set in editor, -1 = up, -2 = down														//+496
	char		*target;																									//+500
	char		*target2;		//For multiple targets, not used for firing/triggering/using, though, only for path branches//+504
	char		*target3;		//For multiple targets, not used for firing/triggering/using, though, only for path branches//+508
	char		*target4;		//For multiple targets, not used for firing/triggering/using, though, only for path branches//+512
	char		*targetJump;																								//+516
	char		*targetname;																								//+520
	char		*team;																										//+524

	union																													//+528
	{
		char	*roff;			// the roff file to use, if there is one
		char	*fxFile;		// name of the external effect file
	} roffFX_t;																												//+532

	int		roff_ctr;		// current roff frame we are playing							//+532

	int			next_roff_time;																//+536
	int			fx_time;		// timer for beam in/out effects.							//+540

//Think Functions
	int			nextthink;//Used to determine if it's time to call e_ThinkFunc again		//+544
	thinkFunc_t		e_ThinkFunc;//Called once every game frame for every ent				//+548
	clThinkFunc_t	e_clThinkFunc;//Think func for equivalent centity						//+552
	reachedFunc_t	e_ReachedFunc;// movers call this when hitting endpoint					//+556
	blockedFunc_t	e_BlockedFunc;															//+560
	touchFunc_t		e_TouchFunc;															//+564
	useFunc_t		e_UseFunc;	//Called by G_UseTargets									//+568
	painFunc_t		e_PainFunc;	//Called by G_Damage when damage is taken					//+572
	dieFunc_t		e_DieFunc;	//Called by G_Damage when health reaches <= 0				//+576

//Health and damage fields
	int			health;																		//+580
	int			max_health;																	//+584
	qboolean	takedamage;																	//+588
	material_t	material;																	//+592
	int			damage;																		//+596
	int			dflags;																		//+604
	//explosives, breakable brushes															//+608
	int			splashDamage;	// quad will increase this without increasing radius		//+612
	int			splashRadius;																//+616
	int			methodOfDeath;																//+620
	int			splashMethodOfDeath;														//+624
	//int			hitLoc;//where you were last hit
	int			locationDamage[HL_MAX];		// Damage accumulated on different body locations	//+628

//Entity pointers
	gentity_t	*chain;																		//+720
	gentity_t	*enemy;																		//+724
	gentity_t	*activator;																	//+728
	gentity_t	*teamchain;		// next entity in team										//+732
	gentity_t	*teammaster;	// master of the team										//+736
	gentity_t	*lastEnemy;																	//+740

//Timing variables, counters and debounce times
	float		wait;																		//+744
	float		random;																		//+748
	int			delay;																		//+752
	qboolean	alt_fire;
	int			count;
	int			bounceCount;
	int			fly_sound_debounce_time;	// wind tunnel
	int			painDebounceTime;
	int			disconnectDebounceTime;
	int			attackDebounceTime;
	int			pushDebounceTime;
	int			aimDebounceTime;
	int			useDebounceTime;

//Unions for miscellaneous fields used under very specific circumstances
	union
	{
		qboolean	trigger_formation;
		qboolean	misc_dlight_active;
		qboolean	has_bounced;	// for thermal Det.  we force at least one bounce to happen before it can do proximity checks
	} miscFields_t;

//Navigation
	int			spawnContents;		// store contents of ents on spawn so nav system can restore them
	int			waypoint;			//Set once per frame, if you've moved, and if someone asks
	int			wayedge;			//Used by doors and breakable things to know what edge goes through them
	int			lastWaypoint;		//To make sure you don't double-back
	int			lastInAirTime;
	int			noWaypointTime;		//Debouncer - so don't keep checking every waypoint in existance every frame that you can't find one
	int			combatPoint;
	vec3_t		followPos;
	int			followPosRecalcTime;
	int			followPosWaypoint;

//Animation
	qboolean	loopAnim;
	int		startFrame;
	int		endFrame;

//Script/ICARUS-related fields
	int				m_iIcarusID;
	int				taskID[NUM_TIDS];
	parms_t			*parms;
	char		*behaviorSet[NUM_BSETS];
	char		*script_targetname;
	int			delayScriptTime;

// Ambient sound info
	char			*soundSet;	//Only used for local sets
	int				setTime;

//Used by cameras to locate subjects
	char			*cameraGroup;

//For damage
	int		noDamageTeam;

// Ghoul2 Animation info
	short			playerModel;
	short			weaponModel[MAX_INHAND_WEAPONS];
	short			handRBolt;
	short			handLBolt;
	short			headBolt;
	short			cervicalBolt;
	short			chestBolt;
	short			gutBolt;
	short			torsoBolt;
	short			crotchBolt;
	short			motionBolt;
	short			kneeLBolt;
	short			kneeRBolt;
	short			elbowLBolt;
	short			elbowRBolt;
	short			footLBolt;
	short			footRBolt;
	short			faceBone;
	short			craniumBone;
	short			cervicalBone;
	short			thoracicBone;
	short			upperLumbarBone;
	short			lowerLumbarBone;
	short			hipsBone;
	short			motionBone;
	short			rootBone;
	short			footLBone;
	short			footRBone;
	short			humerusRBone;

	short			genericBone1;		// For bones special to an entity
	short			genericBone2;
	short			genericBone3;

	short			genericBolt1;		// For bolts special to an entity
	short			genericBolt2;
	short			genericBolt3;
	short			genericBolt4;
	short			genericBolt5;

	qhandle_t		cinematicModel;

//==========================================================================================
	
//FIELDS USED EXCLUSIVELY BY SPECIFIC CLASSES OF ENTITIES
	// Vehicle information.
	// The vehicle object.
	DWORD *m_pVehicle;

	//NPC/Player entity fields
	//FIXME: Make these client only?
	DWORD		*NPC;//Only allocated if the entity becomes an NPC

	//Other NPC/Player-related entity fields
	char		*ownername;//Used by squadpaths to locate owning NPC

//FIXME: Only used by NPCs, move it to gNPC_t
	int			cantHitEnemyCounter;//HACK - Makes them look for another enemy on the same team if the one they're after can't be hit

//Only used by NPC_spawners
	char		*NPC_type;
	char		*NPC_targetname;
	char		*NPC_target;

//Variables used by movers (most likely exclusively by them)
	moverState_t moverState;
	int			soundPos1;
	int			sound1to2;
	int			sound2to1;
	int			soundPos2;
	int			soundLoop;
	gentity_t	*nextTrain;
	gentity_t	*prevTrain;
	vec3_t		pos1, pos2;
	vec3_t		pos3;
	int			sounds;
	char		*closetarget;
	char		*opentarget;
	char		*paintarget;
	int			lockCount;	//for maglocks- actually get put on the trigger for the door

//Variables used only by waypoints (for the most part)
	float		radius;
	
	union
	{
		int		wpIndex;
		int		fxID;			// id of the external effect file
	};

	int			noise_index;

	vec4_t		startRGBA;

	union
	{
		vec4_t		finalRGBA;
		vec3_t		pos4;
		vec3_t		modelAngles;	//for brush entities with an attached md3 model, as an offset to the brush's angles
	};

//FIXME: Are these being used anymore?
	DWORD		*item;			// for bonus items - 
	char		*message;		//Used by triggers to print a message when activated

	float		lightLevel;

	//FIXME: can these be removed/condensed/absorbed?
	//Rendering info
	//int			color;

	//Force effects
	int			forcePushTime;
	int			forcePuller;	//who force-pulled me (so we don't damage them if we hit them)
};

enum	EPointType
{
	PT_NONE = 0,

	PT_WAYNODE,
	PT_COMBATNODE,
	PT_GOALNODE,

	PT_MAX
};

int *delayedShutdown;
int *level_time;

gitem_t	*bg_itemlist;

#define MAX_REFTAGS	128		// Probably more than we'll ever need
#define MAX_REFNAME	32

#define	RTF_NONE	0
#define	RTF_NAVGOAL	0x00000001

cvar_t *g_spskill;
cvar_t *g_subtitles;

void HookGIFuncs( void );
void InitItems( void );
void HookSpawningFuncs( void );
void RemoveSpawnFuncs( void );
void UnhookAll( void );

qboolean SP_Waypoint ( gentity_t *ent );

void SP_NPC_Galak ( gentity_t *ent );
void SP_waypoint_navgoal_1 ( gentity_t *ent );
void SP_waypoint_navgoal_2 ( gentity_t *ent );
void SP_waypoint_navgoal_4 ( gentity_t *ent );
void SP_waypoint_navgoal_8 ( gentity_t *ent );
void SP_misc_model_gun_rack2 ( gentity_t *ent );